﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media.Animation;
using System.Xml;
using FluidKit.Helpers.DragDrop;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace WIAssistant
{

    public delegate void WorkItemMappingMade(FieldDefinition sourceFieldDefinition, FieldDefinition destField, Panel panel);
    public delegate void WorkItemMappingFailed(FieldDefinition sourceFieldDefinition, FieldDefinition destField);

    public class DestinationFieldDropTargetAdvisor : IDropTargetAdvisor
    {
        private readonly FieldDefinition _sourceFieldDefinition;
        private readonly FieldDefinitionCollection _destFields;
        private static readonly DataFormat _supportedFormat = DataFormats.GetDataFormat("FluidKit2");
        private readonly bool _applyMouseOffset;

        public DestinationFieldDropTargetAdvisor(FieldDefinition sourceFieldDefinition, FieldDefinitionCollection destFields,
            WorkItemMappingMade onMappingMade, WorkItemMappingFailed onMappingFailed)
        {
            _sourceFieldDefinition = sourceFieldDefinition;
            _destFields = destFields;
            _applyMouseOffset = true;
            
            if (onMappingMade != null)
                OnMappingMade += onMappingMade;
            if (onMappingFailed != null)
                OnMappingFailed += onMappingFailed;
        }

        #region IDropTargetAdvisor Members

        public bool IsValidDataObject(IDataObject obj)
        {
            return obj.GetDataPresent(_supportedFormat.Name);
        }

        public event WorkItemMappingMade OnMappingMade;
        public event WorkItemMappingFailed OnMappingFailed;

        public void OnDropCompleted(IDataObject obj, Point dropPoint)
        {
            DestinationField destinationField = ExtractElement(obj);
            
            WrapPanel targetPanel = null;
            if(_sourceFieldDefinition != null)
            {
                targetPanel = (WrapPanel)TargetUI;

                // Check to see if this is a valid target.
                if (_sourceFieldDefinition.FieldType != destinationField.DestField.FieldType)
                {
                    // If the data types do not match do not allow the drop.

                    // If the OnMappingFailed event is set then call it.
                    if (OnMappingFailed != null)
                        OnMappingFailed(_sourceFieldDefinition, destinationField.DestField);
                    return;
                }
            }
            
            if (OnMappingMade != null)
                OnMappingMade(_sourceFieldDefinition, destinationField.DestField, targetPanel);
        }

        public UIElement TargetUI { get; set; }

        public bool ApplyMouseOffset
        {
            get { return _applyMouseOffset; }
        }

        public UIElement GetVisualFeedback(IDataObject obj)
        {
            DestinationField destinationField = ExtractElement(obj);

            //ContentControl elt = new ContentControl { Content = destinationField };
            Button elt = new Button{ Content = destinationField.DestField.Name };

            DoubleAnimation anim = new DoubleAnimation(0.75, new Duration(TimeSpan.FromMilliseconds(500)))
            {
                From = 0.25,
                AutoReverse = true,
                RepeatBehavior = RepeatBehavior.Forever
            };
            elt.BeginAnimation(UIElement.OpacityProperty, anim);

            return elt;
        }

        public UIElement GetTopContainer()
        {
            return Application.Current.MainWindow.Content as UIElement;
        }

        #endregion

        private DestinationField ExtractElement(IDataObject obj)
        {
            string xamlString = obj.GetData("FluidKit2") as string;
            if (xamlString != null)
            {
                XmlReader reader = XmlReader.Create(new StringReader(xamlString));
                int fieldID = (int) XamlReader.Load(reader);
                foreach (FieldDefinition destField in _destFields)
                {
                    if (destField.Id == fieldID)
                        return new DestinationField(destField);
                }
            }
            return null;
        }
    }
}
